#include "dahengcameradevice.h"
#include <QDateTime>
#include <QFile>
#include <QImage>
#include <QPixmap>
#include "../mainwindow.h"

DahengCameraDevice::DahengCameraDevice(QObject *parent)
    : Device{parent},
    m_strIP("169.254.24.225"),
    m_nPort(1000)
{
    InitLib();
}

DahengCameraDevice::~DahengCameraDevice(){
    UninitLib();
}

void DahengCameraDevice::InitLib(){
    GX_STATUS emStatus = GXInitLib();
    if(emStatus != GX_STATUS_SUCCESS){
        qDebug() << "Camera Lib 初始化失败...";
    }else{
        qDebug() << "Camera Lib 初始化成功...";
    }
}

void DahengCameraDevice::UninitLib(){
    GX_STATUS emStatus = GXCloseLib();
    if(emStatus != GX_STATUS_SUCCESS){
        qDebug() << "Camera Lib 逆初始化失败...";
    }else{
        qDebug() << "Camera Lib 逆初始化成功...";
    }
}

void DahengCameraDevice::writeXML(QXmlStreamWriter &writer) {
    // 写入当前操作的信息
    writer.writeStartElement("DahengCameraDevice");
    writer.writeAttribute(QStringLiteral("id"), m_strID);

    writer.writeTextElement("ip", m_strIP);
    writer.writeTextElement("port", QString::number(m_nPort));
    writer.writeEndElement(); // 结束当前操作的元素
}

void DahengCameraDevice::readFromXML(QXmlStreamReader &reader){
    QXmlStreamAttributes attributes = reader.attributes();
    if (attributes.hasAttribute("id")) {
        m_strID = attributes.value("id").toString();
    }

    QXmlStreamReader::TokenType token = reader.readNext();
    while (!(reader.tokenType() == QXmlStreamReader::EndElement
             && reader.name() == QStringLiteral("DahengCameraDevice"))) {
        if (reader.name() == QStringLiteral("ip")) {
            m_strIP = reader.readElementText();
        } else if (reader.name() == QStringLiteral("port")) {
            m_nPort = reader.readElementText().toInt();
        }

        reader.readNext();
    }
}

int DahengCameraDevice::OpenCamera(){
    GX_OPEN_PARAM stOpenParam;
    stOpenParam.accessMode = GX_ACCESS_EXCLUSIVE;
    stOpenParam.openMode = GX_OPEN_IP;
    QByteArray ipAddr = ("169.254.24.225");
    stOpenParam.pszContent = ipAddr.data();
    m_emStatus = GXOpenDevice(&stOpenParam,&m_hDevice);
    if(m_emStatus == GX_STATUS_SUCCESS){
        // 设置相机的流通道包长属性，提高网络相机的采集功能
        bool bImplementPacketSize = false;
        uint32_t ui32PacketSize = 0;

        qDebug() << "打开设备成功...";
    }else{
        qDebug() << "打开设备失败...";
        return -1;
    }

    uint32_t	  nDSNum	  = 0;
    // 获取流通道数
    m_emStatus = GXGetDataStreamNumFromDev(m_hDevice, &nDSNum);
    if(m_emStatus == GX_STATUS_SUCCESS){
        qDebug() << "获取流通道数成功...";
    }else{
        qDebug() << "获取流通道数失败...";
        return -1;
    }

    if(0 < nDSNum)
    {
        // 获取流句柄
        m_emStatus = GXGetDataStreamHandleFromDev(m_hDevice, 1, &m_hStream);
        if(m_emStatus == GX_STATUS_SUCCESS){
            qDebug() << "获取流句柄成功...";
        }else{
            qDebug() << "获取流句柄失败...";
            return  -1;
        }
    }

    GX_STATUS emStatus = GX_STATUS_SUCCESS;

    //设置采集模式连续采集
    emStatus = GXSetEnumValueByString(m_hDevice, "AcquisitionMode", "Continuous");

    //设置触发模式为开
    emStatus = GXSetEnumValueByString(m_hDevice, "TriggerMode", "On");

    //选择触发源为软触发
    emStatus = GXSetEnumValueByString(m_hDevice, "TriggerSource", "Software");
    return 0;
}

int DahengCameraDevice::StartCamera(){
    m_emStatus = GXSetEnumValueByString(m_hStream, "StreamBufferHandlingMode", "NewestOnly");

    m_emStatus = GXSetCommandValue(m_hDevice,"AcquisitionStart");
    if(m_emStatus != GX_STATUS_SUCCESS){
        qDebug() << "开始采集失败...";
    }else{
        qDebug() << "开始采集成功...";
    }

    // 得到图像的payloadSize
    uint32_t ui32PayLoadSize = 0;
    m_emStatus = GXGetPayLoadSize(m_hStream, &ui32PayLoadSize);
    //为GetImage参数分配空间
    m_stFrameData.pImgBuf     = new(std::nothrow) BYTE[ui32PayLoadSize];
    if (m_stFrameData.pImgBuf == NULL)
    {
        qDebug() << "分配空间失败...";
    }
    return 0;
}

int DahengCameraDevice::StopCamera(){
    m_emStatus = GXSetCommandValue(m_hDevice,"AcquisitionStop");
    if(m_emStatus != GX_STATUS_SUCCESS){
        qDebug() << "停止采集失败...";
        return -1;
    }else{
        qDebug() << "停止采集成功...";
    }
    return 0;
}

int DahengCameraDevice::initDevice() {
    int nRet = OpenCamera();
    if(nRet == -1){
        return nRet;
    }

    nRet = StartCamera();
    if(nRet == -1){
        return nRet;
    }
    return 0;
}

void DahengCameraDevice::writeBmpFile(char *data, int w, int h,int imageNum)
{
    BITMAPFILEHEADER bitmapfileheader;  //bmp 头文件  14个字节
    bitmapfileheader.bfType = 0x4D42;//表示文件类型，BMP格式的文件这两个字节是0x4D42，10进制就是19778，字符显示就是‘BM’；
    bitmapfileheader.bfReserved1 = 0;//保留位必须设置为0
    bitmapfileheader.bfReserved2 = 0;//保留位必须设置为0
    bitmapfileheader.bfOffBits = 14 + 40;   //4字节的偏移

    BITMAPINFO  bitmapinfo;
    ZeroMemory(&bitmapinfo, sizeof(bitmapinfo));

    bitmapinfo.bmiHeader.biSize = sizeof(bitmapinfo.bmiHeader);  //40byte
    bitmapinfo.bmiHeader.biWidth = w;
    bitmapinfo.bmiHeader.biHeight = h;
    bitmapinfo.bmiHeader.biPlanes = 1;//颜色平面数 一般设置为1
    bitmapinfo.bmiHeader.biBitCount = 24;//每个像素占的bit数  1，2,4,8,16,24,32
    bitmapinfo.bmiHeader.biCompression = BI_RGB;  //压缩类型 常用是0表示不压缩
    bitmapinfo.bmiHeader.biSizeImage = (w * bitmapinfo.bmiHeader.biBitCount + 31) / 32 * 4 * h;//位图的大小
    bitmapinfo.bmiHeader.biClrUsed = 0;//2的biBitCount次方
    bitmapinfo.bmiHeader.biClrImportant = 0;
    bitmapinfo.bmiHeader.biXPelsPerMeter = 0;
    bitmapinfo.bmiHeader.biYPelsPerMeter = 0;

    QString pathname = "d:\\test\\seat\\";
    QString filename = "korol";

    QFile hfile(pathname + filename + QString::number(imageNum) + ".bmp");
    if (hfile.open(QFile::WriteOnly))
    {
        char* bh = reinterpret_cast<char*>(&bitmapfileheader);
        hfile.write(bh, sizeof(bitmapfileheader));

        char *info = reinterpret_cast<char*>(&bitmapinfo);
        hfile.write(info, sizeof(bitmapinfo.bmiHeader));

        hfile.write(data, bitmapinfo.bmiHeader.biSizeImage);
    }
    hfile.close();
}

void DahengCameraDevice::writeData(const QVariant &data){
    QMap<QString,QVariant> map = data.toMap();
    int imageNum = ((QVariant)map["content"]).toInt();
    qDebug() << "content = " << imageNum;

    int m_nEditTimeOut = 500;
    //每次发送触发命令之前清空采集输出队列
    //防止库内部缓存帧，造成本次GXGetImage得到的图像是上次发送触发得到的图
    m_emStatus = GXFlushQueue(m_hDevice);

    //发送软触发命令
    m_emStatus = GXSetCommandValue(m_hDevice,"TriggerSoftware");

    qint64 CurrentMEpoch1 = QDateTime::currentMSecsSinceEpoch();
    //获取图像
    m_emStatus = GXGetImage(m_hDevice, &m_stFrameData, m_nEditTimeOut);

    int nWidth = m_stFrameData.nWidth;
    int nHeight = m_stFrameData.nHeight;

    char* pOutBuffer = MainWindow::instance()->GetImageSrcBuffer(imageNum);

    //char* pOutBuffer = (char*) malloc(nWidth * nHeight * 3 * sizeof(char));

    DxRaw8toRGB24(m_stFrameData.pImgBuf,
                  pOutBuffer,
                  nWidth,
                  nHeight,
                  DX_BAYER_CONVERT_TYPE::RAW2RGB_ADAPTIVE,
                  DX_PIXEL_COLOR_FILTER::BAYERRG,
                  true);

    writeBmpFile(pOutBuffer,nWidth,nHeight,imageNum);

    // 加载BMP图像
    QImage image(nWidth,nHeight,QImage::Format_BGR888);
    memcpy(image.bits(),pOutBuffer,nWidth * nHeight * 3);

    //image.save("D:\\korol1.bmp");
    //img = img.scaled(800,600, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    // 创建QLabel并显示图像
    //free(pOutBuffer);

    qint64 CurrentMEpoch2 = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "采集一张图片，耗时：" << QString::number(CurrentMEpoch2 - CurrentMEpoch1) << "毫秒";
}

void DahengCameraDevice::uninitDevice() {
    UninitLib();
}

QString DahengCameraDevice::getClassName() {
    return this->metaObject()->className();
}
